package com.sgzn.sgpay.service.impl;

import com.sgzn.sgpay.enums.LoginStat;
import com.sgzn.sgpay.enums.SeqFlagEnum;
import com.sgzn.sgpay.enums.SgsResponseCode;
import com.sgzn.sgpay.model.request.LoginReqDto;
import com.sgzn.sgpay.model.request.SgsLoginRequest;
import com.sgzn.sgpay.model.response.LoginRespDto;
import com.sgzn.sgpay.model.response.SgsResultResponse;
import com.sgzn.sgpay.model.response.result.LoginResult;
import com.sgzn.sgpay.persistence.dao.TInRequestMapper;
import com.sgzn.sgpay.persistence.dao.TLoginSessionMapper;
import com.sgzn.sgpay.persistence.dao.TUserMapper;
import com.sgzn.sgpay.persistence.domain.*;
import com.sgzn.sgpay.service.SgsLoginService;
import com.sgzn.sgpay.service.config.AppConfig;
import com.sgzn.sgpay.service.support.HttpRequestHandler;
import com.sgzn.sgpay.util.SeqUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * 登录接口
 * @author zhongzhongyong
 * @version Id: SgsLoginServiceImpl.java, v 0.1 2018/4/5 14:06 zhongzhongyong Exp $$
 */
@Service
@Slf4j
public class SgsLoginServiceImpl implements SgsLoginService{

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private TInRequestMapper tInRequestMapper;

    @Autowired
    private TUserMapper tUserMapper;

    @Autowired
    private TLoginSessionMapper tLoginSessionMapper;

    @Autowired
    private HttpRequestHandler httpRequestHandler;

    @Override
    public SgsResultResponse<LoginResult> login(SgsLoginRequest request) {
        SgsResultResponse sgsResponse = new SgsResultResponse();
        String initId = request.getInitiationID();
        LoginReqDto dto = this.getLoginReqDto(request);
        LoginRespDto loginRespDto = httpRequestHandler.invokeJscode2session(dto,initId);
        LoginResult loginResult = new LoginResult();
        String loginStat = LoginStat.FAIL.getCode();
        if(StringUtils.isNotBlank(loginRespDto.getOpenId())){
            String token = SeqUtil.getShortSeq(SeqFlagEnum.TOKEN.getCode());
            loginResult.setLoginToken(token);
            sgsResponse.setErrorCode(SgsResponseCode.C200.getResponseCode());
            sgsResponse.setErrorMsg(SgsResponseCode.C200.getResponseDesc());
            sgsResponse.setResult(loginResult);
            loginStat = LoginStat.SUCCESS.getCode();
            //登录成功，记录用户信息
            String userId = getUserId(request,loginRespDto.getOpenId());
            //用户登录会话记录
            this.tLoginSessionLog(loginRespDto,userId,token,initId);
        }else{
            sgsResponse.setErrorCode(SgsResponseCode.C503000.getResponseCode());
            sgsResponse.setErrorMsg(SgsResponseCode.C503000.getResponseDesc());
        }
        //记录登录日志
        this.tInRequestLog(request,loginStat);
        return sgsResponse;
    }

    /**
     * 获取登录请求实体
     * @param request
     * @return
     */
    private LoginReqDto getLoginReqDto(SgsLoginRequest request){
        LoginReqDto dto = new LoginReqDto();
        dto.setAppid(appConfig.getAppId());
        dto.setGrant_type(appConfig.getGrantType());
        dto.setSecret(appConfig.getSecret());
        dto.setJs_code(request.getTempCode());
        return dto;
    }

    /**
     * 登录日志表记录
     * @param request
     * @param stat
     */
    private void tInRequestLog(SgsLoginRequest request,String stat){
        TInRequest tInRequest = new TInRequest();
        tInRequest.setLoginDevice(request.getLoginDevice());
        tInRequest.setLoginChannel(request.getLoginChannel());
        tInRequest.setLoginMerchant(request.getLoginMerchant());
        tInRequest.setLoginTime(request.getReqTime());
        tInRequest.setLoginSeq(request.getInitiationID());
        tInRequest.setLoginShop(request.getLoginShop());
        tInRequest.setCreatedAt(new Date());
        tInRequest.setUpdatedAt(new Date());
        tInRequest.setLoginStat(stat);
        try{
            tInRequestMapper.insertSelective(tInRequest);
        }catch (DataAccessException e) {
            log.error("[{}]. 插入响应流水日志异常.{}", request.getInitiationID(),e.getStackTrace());
        }
    }

    /**
     * 用户表记录
     * @param request
     * @param openId
     * @return userId
     */
    private String getUserId(SgsLoginRequest request,String openId){
        String userId = "";
        //根据openId和appId 查询是否存在该用户
        if(StringUtils.isNotBlank(openId)){
            TUserExample tUserExample = new TUserExample();
            TUserExample.Criteria criteria = tUserExample.createCriteria();
            criteria.andOpenidEqualTo(openId).andAppidEqualTo(appConfig.getAppId());
            List<TUser> userList = tUserMapper.selectByExample(tUserExample);
            if(userList != null && userList.size() > 0){
                //已存在用户
                log.info("[{}] 用户已注册 openID:{}",request.getInitiationID(),openId);
                userId= userList.get(0).getUserId();
            }else{
                //新用户注册
                userId = SeqUtil.getShortSeq(SeqFlagEnum.USER_ID.getCode());//32位用户ID
                TUser newUser = new TUser();
                newUser.setAppid(appConfig.getAppId());
                newUser.setOpenid(openId);
                newUser.setUserId(userId);
                newUser.setCreatedAt(new Date());
                newUser.setUpdatedAt(new Date());
                try{
                    tUserMapper.insertSelective(newUser);
                }catch (DataAccessException e) {
                    log.error("[{}]. 插入响应流水日志异常.{}", request.getInitiationID(),e.getStackTrace());
                }
            }
        }
        return userId;
    }

    /**
     * 登录会话表记录
     * @param loginRespDto
     * @param userId
     * @param token
     */
    private void tLoginSessionLog(LoginRespDto loginRespDto,String userId,
                                  String token,String initId){
        //根据openId查找登录会话表是否存在记录
        TLoginSessionExample queryExample = new TLoginSessionExample();
        TLoginSessionExample.Criteria criteria = queryExample.createCriteria();
        criteria.andOpenIdEqualTo(loginRespDto.getOpenId());
        List<TLoginSession> sList = tLoginSessionMapper.selectByExample(queryExample);
        if(sList != null && sList.size()>0){
            //已存在登录历史记录
            Integer hisSessionId = sList.get(0).getId();
            TLoginSession updateSession = new TLoginSession();
            updateSession.setId(hisSessionId);
            updateSession.setSessionKey(loginRespDto.getSessionKey());
            updateSession.setToken(token);
            updateSession.setUnionId(loginRespDto.getUnionId());
            updateSession.setUpdatedAt(new Date());
            tLoginSessionMapper.updateByPrimaryKeySelective(updateSession);
        }else{
            TLoginSession tLoginSession = new TLoginSession();
            tLoginSession.setUserId(userId);
            tLoginSession.setOpenId(loginRespDto.getOpenId());
            tLoginSession.setSessionKey(loginRespDto.getSessionKey());
            tLoginSession.setUnionId(loginRespDto.getUnionId());
            tLoginSession.setToken(token);
            tLoginSession.setCreatedAt(new Date());
            tLoginSession.setUpdatedAt(new Date());
            try{
                tLoginSessionMapper.insertSelective(tLoginSession);
            }catch (DataAccessException e) {
                log.error("[{}]. 插入响应流水日志异常.{}", initId,e.getStackTrace());
            }
        }
    }
}
